import asyncio
import random

import redis
from threading import Thread
from locker import Locker
from async_locker import AioLocker
from time import sleep
from printer import Printer
import aioredis

pool = redis.ConnectionPool(host="127.0.0.1", port=6379, socket_connect_timeout=3, decode_responses=True)
redis_cli = redis.Redis(connection_pool=pool)


def press(tid):
    locker = Locker(redis_cli, 'num_id', tid)
    if locker.lock():
        # 模拟第一个拿到锁让后面999个进入竞争状态
        if tid == '0': sleep(1)
        num = int(redis_cli.get('num'))
        Printer.print(f'press id is {tid}, get lock, num is {num}', color=Printer.OKGREEN)
        if num > 0: redis_cli.set('num', str(num - 1))
        locker.release_lock()
    else:
        Printer.print(f'press id is {tid}, num is {redis_cli.get("num")}', Printer.FAIL)


async def aio_press(cli, aid):
    locker = AioLocker(cli, 'num_id', aid, time_out=5)
    if await locker.lock():
        # 模拟第一个拿到锁，让后面999个进入竞争状态
        if aid == '0': await asyncio.sleep(1)
        num = await cli.get('num')
        num = int(num.decode())
        Printer.print(f'aio_press id is {aid}, get lock, num is {num}', color=Printer.OKGREEN)
        if num > 0: await cli.set('num', str(num -1))
        await locker.release_lock()
    else:
        Printer.print(f'aio_press id is {aid}, num is {redis_cli.get("num")}', Printer.FAIL)

async def start(loop):
    cli = aioredis.from_url('redis://localhost')
    await cli.set('num', '100')
    for i in range(1000):
        loop.create_task(aio_press(cli, str(i)))
        await asyncio.sleep(0.001)

if __name__ == '__main__':
    redis_cli.set('num', '100')
    for i in range(1000):
        t = Thread(target=press, args=(str(i),))
        t.start()
        sleep(0.001)
    loop = asyncio.get_event_loop()
    loop.create_task(start(loop))
    loop.run_forever()